íì ì€í¬ëŠœížì ê°ë ¥í ë§µë íì 곌 ì¡°ê±Žë¶ íì ì ë€ë£šë í¬êŽì ìž ê°ìŽëì ëë€. ì€ì©ì ìž ìì ì ê³ êž íì© ì¬ë¡ë¥Œ íµíŽ ê²¬ê³ íê³ íì -ìì í ì í늬ìŒìŽì ì ë§ëë ë°©ë²ì ë°°ì볎ìžì.
TypeScriptì ë§µë íì 곌 ì¡°ê±Žë¶ íì ë§ì€í°íêž°
ìë°ì€í¬ëŠœížì ìì ì§í©ìž íì ì€í¬ëŠœížë ê²¬ê³ íê³ ì ì§ë³Žìíêž° ì¬ìŽ ì í늬ìŒìŽì ì ë§ë€êž° ìí ê°ë ¥í êž°ë¥ë€ì ì ê³µí©ëë€. ìŽë¬í êž°ë¥ë€ ì€ìì ë§µë íì (Mapped Types)곌 ì¡°ê±Žë¶ íì (Conditional Types)ì ê³ êž íì ì¡°ìì ìí íì ëêµ¬ë¡ ë볎ì ëë€. ìŽ ê°ìŽëë ìŽë¬í ê°ë ì ëí í¬êŽì ìž ê°ì륌 ì ê³µíë©°, ê·ž 구묞, ì€ì ì ì© ì¬ë¡ ë° ê³ êž íì© ì¬ë¡ë¥Œ íìí©ëë€. ìë šë íì ì€í¬ëŠœíž ê°ë°ììŽë ìŽì ë§ ì¬ì ì ììí ë¶ìŽë , ìŽ êžì ìŽë¬í êž°ë¥ë€ì íšê³Œì ìŒë¡ íì©í ì ìë ì§ìì ì ê³µí ê²ì ëë€.
ë§µë íì ìŽë 묎ììžê°ì?
ë§µë íì ì ì¬ì©í멎 Ʞ졎 íì ì ë³ííì¬ ìë¡ìŽ íì ì ë§ë€ ì ììµëë€. Ʞ졎 íì ì ìì±ë€ì ìíí멎ì ê° ìì±ì ë³íì ì ì©í©ëë€. ìŽë 몚ë ìì±ì ì íì ìŽê±°ë ìœêž° ì ì©ìŒë¡ ë§ëë ë± êž°ì¡Ž íì ì ë³íì ìì±íë ë° í¹í ì ì©í©ëë€.
Ʞ볞 구묞
ë§µë íì ì 구묞ì ë€ì곌 ê°ìµëë€:
type NewType<T> = {
[K in keyof T]: Transformation;
};
T: ë§€ííë €ë ì ë ¥ íì ì ëë€.K in keyof T: ì ë ¥ íìTì ê° í€ë¥Œ ìíí©ëë€.keyof TëTì ìë 몚ë ìì± ìŽëŠì ì ëìšì ìì±íê³ ,Kë ë°ë³µ ì€ ê° ê°ë³ í€ë¥Œ ëíë ëë€.Transformation: ê° ìì±ì ì ì©íë €ë ë³íì ëë€. ìŽëreadonlyë?ì ê°ì ìì ì륌 ì¶ê°íê±°ë, íì ì ë³ê²œíê±°ë, ëë ì í ë€ë¥ž ê²ìŒ ì ììµëë€.
ì€ì©ì ìž ìì
ìì±ì ìœêž° ì ì©ìŒë¡ ë§ë€êž°
ì¬ì©ì íë¡íì ëíëŽë ìží°íìŽì€ê° ìë€ê³ ê°ì íŽ ëŽ ìë€:
interface UserProfile {
name: string;
age: number;
email: string;
}
몚ë ìì±ìŽ ìœêž° ì ì©ìž ìë¡ìŽ íì ì ë§ë€ ì ììµëë€:
type ReadOnlyUserProfile = {
readonly [K in keyof UserProfile]: UserProfile[K];
};
ìŽì ReadOnlyUserProfileì UserProfile곌 ëìŒí ìì±ì ê°ì§ë§, 몚ë ìœêž° ì ì©ìŽ ë©ëë€.
ìì±ì ì íì ìŒë¡ ë§ë€êž°
ë¹ì·íê², 몚ë ìì±ì ì íì ìŒë¡ ë§ë€ ì ììµëë€:
type OptionalUserProfile = {
[K in keyof UserProfile]?: UserProfile[K];
};
OptionalUserProfileì UserProfileì 몚ë ìì±ì ê°ì§ë§, ê° ìì±ì ì í ì¬íìŽ ë©ëë€.
ìì± íì ìì íêž°
ê° ìì±ì íì ì ìì í ìë ììµëë€. ì륌 ë€ìŽ, 몚ë ìì±ì 묞ììŽë¡ ë³íí ì ììµëë€:
type StringifiedUserProfile = {
[K in keyof UserProfile]: string;
};
ìŽ ê²œì°, StringifiedUserProfileì 몚ë ìì±ì string íì
ìŽ ë©ëë€.
ì¡°ê±Žë¶ íì ìŽë 묎ììžê°ì?
ì¡°ê±Žë¶ íì ì ì¬ì©í멎 조걎ì ë°ëŒ ë¬ëŒì§ë íì ì ì ìí ì ììµëë€. ìŽë íì ìŽ í¹ì ì ìœ ì¡°ê±Žì ë§ì¡±íëì§ ì¬ë¶ì ë°ëŒ íì êŽê³ë¥Œ íííë ë°©ë²ì ì ê³µí©ëë€. ìŽê²ì ìë°ì€í¬ëŠœížì ìŒí ì°ì°ìì ì ì¬íì§ë§, íì ì ìí ê²ì ëë€.
Ʞ볞 구묞
ì¡°ê±Žë¶ íì ì 구묞ì ë€ì곌 ê°ìµëë€:
T extends U ? X : Y
T: íìžëë íì ì ëë€.U:Tì ìíŽ íì¥ëë íì (조걎)ì ëë€.X:Tê°U륌 íì¥í ê²œì° (ì¡°ê±ŽìŽ ì°žìŒ ë) ë°íë íì ì ëë€.Y:Tê°U륌 íì¥íì§ ìì ê²œì° (ì¡°ê±ŽìŽ ê±°ì§ìŒ ë) ë°íë íì ì ëë€.
ì€ì©ì ìž ìì
íì ìŽ ë¬žììŽìžì§ íìžíêž°
ì
ë ¥ íì
ìŽ ë¬žììŽìŽë©Ž stringì, ê·žë ì§ ììŒë©Ž number륌 ë°ííë íì
ì ë§ë€ìŽ ëŽ
ìë€:
type StringOrNumber<T> = T extends string ? string : number;
type Result1 = StringOrNumber<string>; // string
type Result2 = StringOrNumber<number>; // number
type Result3 = StringOrNumber<boolean>; // number
ì ëìšìì íì ì¶ì¶íêž°
ì¡°ê±Žë¶ íì ì ì¬ì©íì¬ ì ëìš íì ìì í¹ì íì ì ì¶ì¶í ì ììµëë€. ì륌 ë€ìŽ, nullìŽ ìë íì ì ì¶ì¶íë €ë©Ž ë€ì곌 ê°ìŽ í©ëë€:
type NonNullable<T> = T extends null | undefined ? never : T;
type Result4 = NonNullable<string | null | undefined>; // string
ì¬êž°ì Tê° null ëë undefinedìŽë©Ž íì
ì neverê° ëê³ , ìŽë íì
ì€í¬ëŠœížì ì ëìš íì
ëšìíì ìíŽ íí°ë§ë©ëë€.
íì ì¶ë¡ íêž°
ì¡°ê±Žë¶ íì
ì infer í€ìë륌 ì¬ì©íì¬ íì
ì ì¶ë¡ íë ë°ìë ì¬ì©ë ì ììµëë€. ìŽë¥Œ íµíŽ ë ë³µì¡í íì
구조ìì íì
ì ì¶ì¶í ì ììµëë€.
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
function myFunction(x: number): string {
return x.toString();
}
type Result5 = ReturnType<typeof myFunction>; // string
ìŽ ìì ìì ReturnTypeì íšìì ë°í íì
ì ì¶ì¶í©ëë€. Tê° ììì ìžì륌 ë°ê³ íì
Rì ë°ííë íšììžì§ íìží©ëë€. ë§ìœ ê·žë ë€ë©Ž Rì ë°ííê³ , ê·žë ì§ ìë€ë©Ž any륌 ë°íí©ëë€.
ë§µë íì 곌 ì¡°ê±Žë¶ íì ê²°í©íêž°
ë§µë íì 곌 ì¡°ê±Žë¶ íì ì ì§ì í íì ìŽë€ì ê²°í©í ë ëíë©ëë€. ìŽë¥Œ íµíŽ ë§€ì° ì ì°íê³ ííë ¥ìŽ íë¶í íì ë³íì ë§ë€ ì ììµëë€.
ìì : Deep Readonly
ìŒë°ì ìž ì¬ì© ì¬ë¡ë ì€ì²©ë ìì±ì í¬íšíì¬ ê°ì²Žì 몚ë ìì±ì ìœêž° ì ì©ìŒë¡ ë§ëë íì ì ìì±íë ê²ì ëë€. ìŽë ì¬ê·ì ìž ì¡°ê±Žë¶ íì ì ì¬ì©íì¬ ë¬ì±í ì ììµëë€.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
interface Company {
name: string;
address: {
street: string;
city: string;
};
}
type ReadonlyCompany = DeepReadonly<Company>;
ì¬êž°ì DeepReadonlyë 몚ë ìì±ê³Œ ê·ž ì€ì²©ë ìì±ì readonly ìì ì륌 ì¬ê·ì ìŒë¡ ì ì©í©ëë€. ë§ìœ ìì±ìŽ ê°ì²ŽìŽë©Ž íŽë¹ ê°ì²Žì ëíŽ DeepReadonly륌 ì¬ê·ì ìŒë¡ ížì¶í©ëë€. ê·žë ì§ ììŒë©Ž ìì±ì ëšìí readonly ìì ì륌 ì ì©í©ëë€.
ìì : íì ë³ë¡ ìì± íí°ë§íêž°
í¹ì íì ì ìì±ë§ í¬íšíë íì ì ë§ë€ê³ ì¶ë€ê³ ê°ì íŽ ëŽ ìë€. ë§µë íì 곌 ì¡°ê±Žë¶ íì ì ê²°í©íì¬ ìŽë¥Œ ë¬ì±í ì ììµëë€.
type FilterByType<T, U> = {
[K in keyof T as T[K] extends U ? K : never]: T[K];
};
interface Person {
name: string;
age: number;
isEmployed: boolean;
}
type StringProperties = FilterByType<Person, string>; // { name: string; }
type NonStringProperties = Omit<Person, keyof StringProperties>;
ìŽ ìì ìì FilterByTypeì Tì ìì±ë€ì ìííë©° ê° ìì±ì íì
ìŽ U륌 íì¥íëì§ íìží©ëë€. ë§ìœ ê·žë ë€ë©Ž 결곌 íì
ì íŽë¹ ìì±ì í¬íšìí€ê³ , ê·žë ì§ ìë€ë©Ž í€ë¥Œ neverë¡ ë§€ííì¬ ì ìží©ëë€. í€ë¥Œ 늬맀ííêž° ìíŽ "as"륌 ì¬ì©íë ì ì ì ìíìžì. ê·žë° ë€ì `Omit`곌 `keyof StringProperties`륌 ì¬ì©íì¬ ì볞 ìží°íìŽì€ìì 묞ììŽ ìì±ì ì ê±°í©ëë€.
ê³ êž íì© ì¬ë¡ ë° íšíŽ
Ʞ볞ì ìž ìì 륌 ëìŽì, ë§µë íì 곌 ì¡°ê±Žë¶ íì ì ê³ ëë¡ ì¬ì©ì ì ì ê°ë¥íê³ íì -ìì í ì í늬ìŒìŽì ì ë§ë€êž° ìí ë ê³ êž ìë늬ì€ìì ì¬ì©ë ì ììµëë€.
ë¶ë°°ì ì¡°ê±Žë¶ íì (Distributive Conditional Types)
ì¡°ê±Žë¶ íì ì íìžëë íì ìŽ ì ëìš íì ìŒ ë ë¶ë°°ì (distributive)ì ëë€. ìŽë ì¡°ê±ŽìŽ ì ëìšì ê° ë©€ë²ì ê°ë³ì ìŒë¡ ì ì©ëê³ , ê·ž ê²°ê³Œê° ìë¡ìŽ ì ëìš íì ìŒë¡ ê²°í©ëë€ë ê²ì ì믞í©ëë€.
type ToArray<T> = T extends any ? T[] : never;
type Result6 = ToArray<string | number>; // string[] | number[]
ìŽ ìì ìì ToArrayë ì ëìš string | numberì ê° ë©€ë²ì ê°ë³ì ìŒë¡ ì ì©ëìŽ string[] | number[]ê° ë©ëë€. ë§ìœ ì¡°ê±ŽìŽ ë¶ë°°ì ìŽì§ ììë€ë©Ž 결곌ë (string | number)[]ê° ëìì ê²ì
ëë€.
ì ížëŠ¬í° íì ì¬ì©íêž°
íì ì€í¬ëŠœížë ë§µë íì 곌 ì¡°ê±Žë¶ íì ì íì©íë ì¬ë¬ ëŽì¥ ì ížëŠ¬í° íì ì ì ê³µí©ëë€. ìŽë¬í ì ížëŠ¬í° íì ì ë ë³µì¡í íì ë³íì ìí êµ¬ì± ììë¡ ì¬ì©ë ì ììµëë€.
Partial<T>:Tì 몚ë ìì±ì ì íì ìŒë¡ ë§ëëë€.Required<T>:Tì 몚ë ìì±ì íìë¡ ë§ëëë€.Readonly<T>:Tì 몚ë ìì±ì ìœêž° ì ì©ìŒë¡ ë§ëëë€.Pick<T, K>:Tìì ìì± ì§í©K륌 ì íí©ëë€.Omit<T, K>:Tìì ìì± ì§í©K륌 ì ê±°í©ëë€.Record<K, T>: íì ìŽTìž ìì± ì§í©K륌 ê°ë íì ì 구ì±í©ëë€.Exclude<T, U>:TììUì í ë¹ ê°ë¥í 몚ë íì ì ì ìží©ëë€.Extract<T, U>:TììUì í ë¹ ê°ë¥í 몚ë íì ì ì¶ì¶í©ëë€.NonNullable<T>:Tììnull곌undefined륌 ì ìží©ëë€.Parameters<T>: íšì íìTì ë§€ê°ë³ì íì ì ì»ìµëë€.ReturnType<T>: íšì íìTì ë°í íì ì ì»ìµëë€.InstanceType<T>: ìì±ì íšì íìTì ìžì€íŽì€ íì ì ì»ìµëë€.
ìŽë¬í ì ížëŠ¬í° íì
ë€ì ë³µì¡í íì
ì¡°ìì ëšìíí ì ìë ê°ë ¥í ë구ì
ëë€. ì륌 ë€ìŽ, Pick곌 Partialì ê²°í©íì¬ í¹ì ìì±ë§ ì íì ìŒë¡ ë§ëë íì
ì ìì±í ì ììµëë€:
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
interface Product {
id: number;
name: string;
price: number;
description: string;
}
type OptionalDescriptionProduct = Optional<Product, "description">;
ìŽ ìì ìì OptionalDescriptionProductë Productì 몚ë ìì±ì ê°ì§ì§ë§, description ìì±ì ì í ì¬íì
ëë€.
í í늿 늬í°ëŽ íì ì¬ì©íêž°
í í늿 늬í°ëŽ íì ì ì¬ì©í멎 묞ììŽ ëŠ¬í°ëŽì êž°ë°ìŒë¡ íì ì ìì±í ì ììµëë€. ìŽë ë§µë íì ë° ì¡°ê±Žë¶ íì 곌 ê²°í©íì¬ ëì ìŽê³ ííë ¥ìŽ íë¶í íì ë³íì ë§ëë ë° ì¬ì©ë ì ììµëë€. ì륌 ë€ìŽ, 몚ë ìì± ìŽëŠì í¹ì 묞ììŽ ì ëì¬ë¥Œ ë¶ìŽë íì ì ë§ë€ ì ììµëë€:
type Prefix<T, P extends string> = {
[K in keyof T as `${P}${string & K}`]: T[K];
};
interface Settings {
apiUrl: string;
timeout: number;
}
type PrefixedSettings = Prefix<Settings, "data_">;
ìŽ ìì ìì PrefixedSettingsë data_apiUrl곌 data_timeout ìì±ì ê°ê² ë©ëë€.
ëªšë² ì¬ë¡ ë° ê³ ë €ì¬í
- ëšìíš ì ì§: ë§µë íì 곌 ì¡°ê±Žë¶ íì ì ê°ë ¥íì§ë§ ìœë륌 ë ë³µì¡íê² ë§ë€ ìë ììµëë€. íì ë³íì ê°ë¥í í ëšìíê² ì ì§íë €ê³ ë žë ¥íìžì.
- ì ížëŠ¬í° íì ì¬ì©: ê°ë¥í ëë§ë€ íì ì€í¬ëŠœížì ëŽì¥ ì ížëŠ¬í° íì ì íì©íìžì. ìŽë€ì ì í ì€ížëììŒë©° ìœë륌 ëšìíí ì ììµëë€.
- íì 묞ìí: íì ë³í, í¹í ë³µì¡í ê²œì° ëª ííê² ë¬žìííìžì. ìŽë ë€ë¥ž ê°ë°ìë€ìŽ ìœë륌 ìŽíŽíë ë° ëììŽ ë©ëë€.
- íì í ì€íž: íì ì€í¬ëŠœížì íì ê²ì¬ë¥Œ ì¬ì©íì¬ íì ë³íìŽ ììëë¡ ìëíëì§ íìžíìžì. ëšì í ì€ížë¥Œ ìì±íì¬ íì ì ëìì ê²ìŠí ì ììµëë€.
- ì±ë¥ ê³ ë €: ë³µì¡í íì ë³íì íì ì€í¬ëŠœíž ì»ŽíìŒë¬ì ì±ë¥ì ìí¥ì ì€ ì ììµëë€. íì ì ë³µì¡ì±ì ì ìíê³ ë¶íìí ê³ì°ì íŒíìžì.
ê²°ë¡
ë§µë íì 곌 ì¡°ê±Žë¶ íì ì íì ì€í¬ëŠœížì ê°ë ¥í êž°ë¥ìŒë¡, ë§€ì° ì ì°íê³ ííë ¥ìŽ íë¶í íì ë³íì ê°ë¥íê² í©ëë€. ìŽë¬í ê°ë ì ë§ì€í°íšìŒë¡ìš íì ì€í¬ëŠœíž ì í늬ìŒìŽì ì íì ìì ì±, ì ì§ë³Žìì± ë° ì ë°ì ìž íì§ì í¥ììí¬ ì ììµëë€. ìì±ì ì íì ìŽê±°ë ìœêž° ì ì©ìŒë¡ ë§ëë ê°ëší ë³íë¶í° ë³µì¡í ì¬ê· ë³í ë° ì¡°ê±Žë¶ ë¡ì§ì ìŽë¥Žêž°ê¹ì§, ìŽë¬í êž°ë¥ë€ì ê²¬ê³ íê³ íì¥ ê°ë¥í ì í늬ìŒìŽì ì 구ì¶íë ë° íìí ë구륌 ì ê³µí©ëë€. ìŽë¬í êž°ë¥ë€ì ì ì¬ë ¥ì ìµëí ë°ííê³ ë ë¥ìí íì ì€í¬ëŠœíž ê°ë°ìê° ëêž° ìíŽ ê³ìíŽì íìíê³ ì€ííŽ ë³Žìžì.
íì ì€í¬ëŠœíž ì¬ì ì ê³ìí멎ì ê³µì íì ì€í¬ëŠœíž ë¬žì, ìšëŒìž 컀뮀ëí°, ì€í ìì€ íë¡ì íž ë± ì¬ì© ê°ë¥í íë¶í 늬ìì€ë¥Œ íì©íë ê²ì ìì§ ë§ìžì. ë§µë íì 곌 ì¡°ê±Žë¶ íì ì íì ë°ìë€ìŽë©Ž ê°ì¥ ìŽë €ìŽ íì êŽë š 묞ì ìë ì ëì²í ì ìì ê²ì ëë€.